/* Copyright (c) 2012 Ronan Mac an tSaoir

	 Licensed under the Apache License, Version 2.0 (the "License");
	 you may not use this file except in compliance with the License.
	 You may obtain a copy of the License at

		 http://www.apache.org/licenses/LICENSE-2.0

	 Unless required by applicable law or agreed to in writing, software
	 distributed under the License is distributed on an "AS IS" BASIS,
	 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
	 See the License for the specific language governing permissions and
	 limitations under the License.
*/

package com.enjoyireland.hiking;

import java.text.DecimalFormat;

import uk.me.jstott.jcoord.IrishRef;
import uk.me.jstott.jcoord.LatLng;
import android.content.Intent;
import android.database.Cursor;
import android.location.Criteria;
import android.location.Location;
import android.location.LocationManager;
import android.net.Uri;
import android.os.Bundle;
import android.support.v4.app.ListFragment;
import android.support.v4.app.LoaderManager;
import android.support.v4.content.CursorLoader;
import android.support.v4.content.Loader;
import android.support.v4.widget.SimpleCursorAdapter;
import android.support.v4.widget.SimpleCursorAdapter.ViewBinder;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.ListView;
import android.widget.RatingBar;
import android.widget.TextView;

/**
 * ListFragment for loading list of walks from database
 * 
 * @author Rónan Mac an tSaoir
 * 
 */
public class WalkList extends ListFragment implements LoaderManager.LoaderCallbacks<Cursor>, Constants {
	private SimpleCursorAdapter _adapter;
	/* store positions and distances, sort distances, wrap cursor and move to position of next shortest distance */
	//private HashMap<Integer,Double> _storedPositons;
	
	private boolean _nullLocation = false;
	
	private String _walkChoice = null;
	private String _sortChoice = null;
	
	private static final String[] FROM = {"name","dist","gridref","diff"};
	private static final int[] TO = {R.id.walkName,R.id.walkLength,R.id.walkDist,R.id.walkDiff};
	
	@Override
	public void onActivityCreated(Bundle savedInstanceState) {
		super.onActivityCreated(savedInstanceState);
		/* configure */
		setRetainInstance(true);
		setHasOptionsMenu(true);
		setListShown(false);
		
		/* create empty cursor adapter */
		LayoutInflater.from(getActivity());
		if (_adapter == null) {
			_adapter = new SimpleCursorAdapter(getActivity(), R.layout.db_entry, null, FROM, TO, 0);
		}
		
		/* add headings */
		getListView().addHeaderView(getLayoutInflater(savedInstanceState).inflate(R.layout.db, null));
		
		/* If lastLocation is null, don't do GPS distance, load difficulty instead */
		Location loc = null;
		// bugfix for airplane mode, where providers are deactivated
		try{
			final LocationManager locMgr = (LocationManager) getActivity().getSystemService(getActivity().LOCATION_SERVICE);
			final String provider = locMgr.getBestProvider(new Criteria(), true);
			loc = locMgr.getLastKnownLocation(provider);
		}catch(RuntimeException e){
			_nullLocation=true;
			((TextView)getListView().findViewById(R.id.distHeader)).setText(R.string.walkDiff);
		}
		// GPS or Wirelss have never been used
		if (loc == null){
			_nullLocation=true;
			((TextView)getListView().findViewById(R.id.distHeader)).setText(R.string.walkDiff);
		}
			
		getListView().setAdapter(_adapter);
		
		/* format db contents before updating view
		 * 		Default: show distance to each walk */
		_adapter.setViewBinder(new ViewBinder() {
		    public boolean setViewValue(View aView, Cursor aCursor, int aColumnIndex) {
		    	// bugfix for airplane mode, where providers are deactivated
		    	boolean nullLocation = false;
		    	Location loc = null;
				try{
					final LocationManager locMgr = (LocationManager) getActivity().getSystemService(getActivity().LOCATION_SERVICE);
					final String provider = locMgr.getBestProvider(new Criteria(), true);
					loc = locMgr.getLastKnownLocation(provider);
				}catch(RuntimeException e){
					nullLocation=true;
				}
				// GPS or Wirelss have never been used
				if (loc == null){
					nullLocation=true;
				}
		    	/* 
		    	 * Edit Distance column
		    	 * 	- Check last GPS location
		    	 *  - Calculate distance from specified gridReference to this location
		    	 *  - use this value in view and append "km" */
		        if (nullLocation == false && aColumnIndex == COL_GRID_INDEX) {
		        	// get last best location
					if (loc !=null){
						// convert grid reference to lat/lng
						IrishRef gr = new IrishRef(aCursor.getString(aColumnIndex));
						LatLng walkLoc = gr.toLatLng();
						// get distance between points
						double distance = MapUtils.getDistance(new LatLng(loc.getLatitude(), loc.getLongitude()),walkLoc);
						// update view with rounded distance
		                ((TextView) aView).setText(new DecimalFormat("#.##").format(distance) + " km");
		                //store position and distance value
		                //_storedPositons.put(aCursor.getPosition(), distance);
		                if (_nullLocation)
		                	aView.setVisibility(View.INVISIBLE);
		                return true;
					}
		         }
		        else if (aColumnIndex == COL_GRID_INDEX){
					aView.setVisibility(View.INVISIBLE);
					return true;
				}
		        /* no location found, load difficulty instead */
		        if (aColumnIndex == COL_DIFF_INDEX){
					// show rating bar with stars representing difficulty (num of stars stored in DB)
		        	if (nullLocation)
		        		aView.setVisibility(View.VISIBLE);
					((RatingBar)aView).setNumStars(aCursor.getInt(COL_DIFF_INDEX));
					return true;
		        }
		        if (aColumnIndex == COL_LEN_INDEX){
					// append "km" to walk length
					((TextView)aView).setText(aCursor.getString(COL_LEN_INDEX)+" km");
					return true;
		        }
				return false;
		    }
		});
		
		/* start loading */
		getLoaderManager().initLoader(0, null, this);
	}
	
    @Override public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
    	super.onCreateOptionsMenu(menu, inflater);
    	menu.add(0, 0, 0, R.string.wRecent).setIcon(R.drawable.ic_menu_mapmode);
    	menu.add(0, 1, 0, R.string.walkLength).setIcon(R.drawable.ic_menu_sort_by_size);
    	menu.add(0, 2, 0, R.string.walkDiff).setIcon(R.drawable.full_star);
    	menu.add(0, 3, 0, R.string.walkAZ).setIcon(R.drawable.ic_menu_sort_alphabetically);
    }
   
	public boolean onRecentMenuSelected(MenuItem item){
		//requery for recent walks
		_walkChoice = COL_VIEWED + " = 'true'";
        setListShown(false);
        _adapter.notifyDataSetChanged();
        getLoaderManager().restartLoader(0, null, this);
        return true;
	}
	public boolean onLengthMenuSelected(MenuItem item){
		//requery for sorting by length
		_sortChoice = COL_LEN;
        setListShown(false);
        getLoaderManager().restartLoader(0, null, this);
        _adapter.notifyDataSetChanged();
        return true;
	}
	public boolean onDiffMenuSelected(MenuItem item){
		//requery for sorting by difficulty
		_sortChoice = COL_DIFF;
		_nullLocation=true;
        setListShown(false);
        getLoaderManager().restartLoader(0, null, this);
        _adapter.notifyDataSetChanged();
        return true;
	}
	public boolean onAlphaMenuSelected(MenuItem item){
		//requery for sorting by name
		_sortChoice = COL_NAME;
        setListShown(false);
        getLoaderManager().restartLoader(0, null, this);
        _adapter.notifyDataSetChanged();
        return true;
	}
	
	@Override
	public void onListItemClick (ListView l, View v, int position, long id){
		Intent i = new Intent(getActivity().getApplicationContext(),WalkTabs.class);
		Uri data = Uri.parse(WalkContentProvider.CONTENT_URI.toString()+"/"+id);
		i.setData(data);
		startActivity(i);
	}
	
	@Override
	public void onLoadFinished(Loader<Cursor> loader, Cursor result) {
		_adapter.swapCursor(result);
		setListShown(true);
		_sortChoice = null;
		_walkChoice = null;
		_nullLocation = false;
		_adapter.notifyDataSetChanged();
	}

	@Override
	public void onLoaderReset(Loader<Cursor> loader) {
		_adapter.swapCursor(null);
	}

	@Override
	public Loader<Cursor> onCreateLoader(int arg0, Bundle arg1) {
		String[] projection = { COL_NAME, COL_LEN, COL_GRID, COL_DIFF, ID };
        return new CursorLoader(getActivity(), WalkContentProvider.CONTENT_URI, projection, _walkChoice, null,_sortChoice);
	}
}